﻿using Microsoft.EntityFrameworkCore;
using SmartWMS.Common.Extensions;
using SmartWMS.Common.ResponseOutput;
using SmartWMS.Domain.Base;
using SmartWMS.Domain.BasicsDatum;
using SmartWMS.Domain.BusinessManage;
using SmartWMS.Domain.FinanceManage;
using SmartWMS.Domain.StatementManage;
using SmartWMS.Domain.SystemSet;
using SmartWMS.Domain.WarehouseManage;
using SmartWMS.EntityFramework;
using SmartWMS.Server.BasicsDatumServer.LocationServer.Dto;
using SmartWMS.Server.BusinessServer.ProcureMentServices.Dto;
using SmartWMS.Server.Repository;
using SmartWMS.Server.WarehouseManage.CheckServer.Dto;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;

namespace SmartWMS.Server.BusinessServer.ProcureMentServices
{
    public class ProcureMentService : IProcureMentService
    {
        private readonly IRepository<ProcureManagement> _procureManagementRepository;

        private readonly IRepository<Product> _productRepository;

        private readonly IRepository<Shopping> _shoppingRepository;

        private readonly IRepository<Supplier> _supplierRepository;

        private readonly IRepository<SalesManagement> _SalesManagementRepository;

        private readonly IRepository<Payment> _paymentRepository;

        private readonly IRepository<ProcuremenReturn> _procuremenReturnRepository;

        private readonly SmartWMSContext _smartWMSContext;


        public ProcureMentService(IRepository<ProcureManagement> procureManagementRepository, IRepository<Product> productRepository, IRepository<Shopping> shoppingRepository, IRepository<Supplier> supplierRepository, IRepository<SalesManagement> salesManagementRepository, IRepository<Payment> paymentRepository, SmartWMSContext smartWMSContext, IRepository<ProcuremenReturn> procuremenReturnRepository)
        {
            _procureManagementRepository = procureManagementRepository;
            _productRepository = productRepository;
            _shoppingRepository = shoppingRepository;
            _supplierRepository = supplierRepository;
            _SalesManagementRepository = salesManagementRepository;
            _paymentRepository = paymentRepository;
            _smartWMSContext = smartWMSContext;
            _procuremenReturnRepository = procuremenReturnRepository;
        }

        /// <summary>
        /// 采购管理列表
        /// </summary>
        /// <param name="select"></param>
        /// <returns></returns>
        public Task<Response<List<ProcureMentDtos>>> CatProcureMentList(ProcureSelect select)
        {
            var procureManagement = _procureManagementRepository.GetListQuery();
            var product = _productRepository.GetListQuery();
            var shopping = _shoppingRepository.GetListQuery();
            var supplier = _supplierRepository.GetListQuery();
            var list = (from p in procureManagement
                        join s in shopping on p.ProcurementCode equals s.ProcuremenCode
                        join pr in product on s.ProductId equals pr.Id
                        join su in supplier on pr.DefaultSupplierId equals su.Id
                        select new ProcureMentDtos
                        {
                            Id = p.Id,
                            ProcurementCode = p.ProcurementCode,
                            ProductName = pr.ProductName,
                            ProductCode = pr.ProductCode,
                            SupplierCode = p.SupplierCode,
                            SupplierName = su.SupplierName,
                            ProcurementProcurement = p.ProcurementProcurement,
                            ProcurementTime = p.ProcurementTime,
                            ProcurementState = p.ProcurementState,
                            SaleCode = p.SaleCode,
                            DocumentType = p.DocumentType,
                            DocumentState = p.DocumentState,
                            Phone = p.Phone,
                            Remark = p.Remark,
                            ContactName = p.ContactName,
                            MakerName = p.MakerName,
                            MakerTime = p.MakerTime,
                            ReceiptTime = p.ReceiptTime,
                            IsReFund = p.IsReFund,
                            Specs = pr.Specs,
                            Unit = pr.Unit,
                            Price = pr.Price,
                            SumPrice = s.SumPrice,
                            BuyNumber = s.BuyNumber,
                        }).ToList();
            if (!string.IsNullOrEmpty(select.procurementCode))
            {
                list = list.Where(x => x.ProcurementCode.Contains(select.procurementCode)).ToList();
            }
            if (!string.IsNullOrEmpty(select.productCode))
            {
                list = list.Where(x => x.ProductCode.Contains(select.productCode)).ToList();
            }
            if (!string.IsNullOrEmpty(select.name))
            {
                list = list.Where(x => x.ProductName.Contains(select.name)).ToList();
            }
            if (select.state != 0)
            {
                list = list.Where(x => x.ProcurementState == select.state).ToList();
            }

            int totalCount = list.Count();
            int pageCount = (int)Math.Ceiling(totalCount / (double)select.pageSize);
            list = list.Skip((select.pageIndex - 1) * select.pageSize).Take(select.pageSize).ToList();
            return Task.FromResult(new Response<List<ProcureMentDtos>> { Data = list, TotalCount = totalCount, PageCount = pageCount });
        }

        /// <summary>
        /// 添加采购管理表和采购产品关联表
        /// </summary>
        /// <param name="procureMentDto"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        public async Task<Response<bool>> AddProcureMent(ProcureMentDtos procureMentDto)
        {


            var shopList = procureMentDto.ShoppingList;
            var list = shopList.Select(x => new Shopping
            {
                ProductId = x.Id,
                ProcuremenCode = procureMentDto.ProcurementCode,
                BuyNumber = x.BuyNumber,
                SumPrice = x.SumPrice,
            }).ToList();
            using (var tran = _smartWMSContext.Database.BeginTransaction())
            {
                try
                {
                    procureMentDto.IsReFund = false;
                    procureMentDto.ProcurementProcurement = false;
                    procureMentDto.ProcurementState = ProcurementState.采购中;
                    var result = await _procureManagementRepository.InsertAsync(procureMentDto.MapTo<ProcureManagement>());
                    if (result > 0)
                    {
                        var shoppingResult = await _shoppingRepository.InsertAsync(list);
                        if (shoppingResult > 0)
                        {
                            _smartWMSContext.MessageCenter.Add(new MessageCenter
                            {
                                MsgTitle = "采购",
                                MsgContent = DateTime.Now + "采购单号为" + procureMentDto.ProcurementCode + "的采购单已经提交",
                                MsgType = "采购信息",
                                MsgState = "采购信息",
                                MsgTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
                            });
                            var result1 = await _smartWMSContext.SaveChangesAsync();
                            if (result1 > 0)
                            {
                                tran.Commit();
                                return Response<bool>.Ok(true);
                            }
                            else
                            {
                                tran.Rollback();
                                return Response<bool>.Fail(false);
                            }
                        }
                        else
                        {
                            tran.Rollback();
                            return Response<bool>.Fail(false);
                        }
                    }
                    else
                    {
                        tran.Rollback();
                        return Response<bool>.Fail(false);
                    }
                }
                catch (Exception)
                {

                    throw;
                }
            }
        }

        /// <summary>
        /// 销售单号列表
        /// </summary>
        /// <returns></returns>4580048090196
        /// 
        public Task<Response<List<SalesManagementDto>>> GetSalesCodeList()
        {
            var salesManagement = _SalesManagementRepository.GetListQuery();
            var list = (from s in salesManagement
                        select new SalesManagementDto
                        {
                            SalesCode = s.SalesCode,
                        }).ToList();
            return Task.FromResult(new Response<List<SalesManagementDto>> { Data = list });
        }

        /// <summary>
        /// 根据销售单号获取销售单信息
        /// </summary>
        /// <param name="code"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        public async Task<Response<SalesManagementDto>> GetSalesManagementByCode(string? code)
        {
            var salesManagement = _SalesManagementRepository.GetListQuery();
            var product = _productRepository.GetListQuery();
            var supplier = _supplierRepository.GetListQuery();
            var list = (from s in salesManagement
                        join p in product on s.ProductId equals p.Id
                        join su in supplier on p.DefaultSupplierId equals su.Id
                        where s.SalesCode == code
                        select new SalesManagementDto
                        {
                            Id = s.Id,
                            SalesCode = s.SalesCode,
                            ProductId = s.ProductId,
                            OutboundShipments = s.OutboundShipments,
                            ClientCode = s.ClientCode,
                            ClientName = s.ClientName,
                            Phone = s.Phone,
                            OrdersSum = s.OrdersSum,
                            DocumentType = s.DocumentType,
                            Delivery = s.Delivery,
                            Creator = s.Creator,
                            CreatorTime = s.CreatorTime,
                            RecordedState = s.RecordedState,
                            State = s.State,
                            Remarks = s.Remarks,
                            SupplierCode = su.SupplierCode

                        }).FirstOrDefault();
            return Response<SalesManagementDto>.Ok(list);

        }

        /// <summary>
        /// 根据采购单号获取采购单信息
        /// </summary>
        /// <param name="code"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        public async Task<Response<ProcureMentDtos>> GetProcureManagementByCode(string? code)
        {
            var procureManagement = _procureManagementRepository.GetListQuery();
            var product = _productRepository.GetListQuery();
            var supplier = _supplierRepository.GetListQuery();
            var shopping = _shoppingRepository.GetListQuery();
            var list = (from p in procureManagement
                        join s in shopping on p.ProcurementCode equals s.ProcuremenCode
                        join pr in product on s.ProductId equals pr.Id
                        join su in supplier on p.SupplierCode equals su.SupplierCode
                        where p.ProcurementCode == code
                        select new ProcureMentDtos
                        {
                            Id = p.Id,
                            ProcurementCode = p.ProcurementCode,
                            DocumentType = p.DocumentType,
                            SaleCode = p.SaleCode,
                            SupplierCode = p.SupplierCode,
                            ClientName = p.ClientName,
                            ContactName = p.ContactName,
                            Phone = p.Phone,
                            ReceiptTime = p.ReceiptTime,
                            MakerName = p.MakerName,
                            MakerTime = p.MakerTime,
                            Remark = p.Remark,
                            ShoppingList = (from sh in shopping
                                            join pr in product on sh.ProductId equals pr.Id
                                            where sh.ProcuremenCode == p.ProcurementCode
                                            select new ShoppingDto
                                            {
                                                Id = pr.Id,
                                                ProductName = pr.ProductName,
                                                ProductCode = pr.ProductCode,
                                                BuyNumber = sh.BuyNumber,
                                                SumPrice = sh.SumPrice,
                                                Specs = pr.Specs,
                                                Unit = pr.Unit,
                                                Price = pr.Price,
                                            }).ToList()


                        }).FirstOrDefault();
            return Response<ProcureMentDtos>.Ok(list);

        }

        /// <summary>
        ///  删除采购管理
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        public async Task<Response<bool>> DeleteProcureMent(ProcureSelect dto)
        {
            try
            {
                var list = _procureManagementRepository.GetListQuery().FirstOrDefault(t => t.ProcurementCode == dto.procurementCode);
                var plist = await _shoppingRepository.GetAllListAsync();
                plist = plist.Where(t => t.ProcuremenCode == dto.procurementCode).ToList();

                if (list != null)
                {
                    using (var tran = _smartWMSContext.Database.BeginTransaction())
                    {
                        try
                        {
                            var result = await _procureManagementRepository.DeleteByIdAsync(list);
                            if (result > 0)
                            {

                                if (plist != null)
                                {
                                    var i = await _shoppingRepository.DeleteAsync(plist);
                                    if (i > 0)
                                    {
                                        tran.Commit();
                                        return Response<bool>.Ok(true);
                                    }
                                    else
                                    {
                                        //回滚
                                        tran.Rollback();
                                        return Response<bool>.Fail(false);
                                    }
                                }
                                else
                                {
                                    //回滚
                                    tran.Rollback();
                                    return Response<bool>.Fail(false);
                                }
                            }
                            else
                            {
                                //回滚
                                tran.Rollback();
                                return Response<bool>.Fail(false);
                            }
                        }
                        catch (Exception)
                        {
                            //回滚
                            tran.Rollback();
                            throw;
                        }
                    }

                }
                else
                {
                    return Response<bool>.Fail(false);
                }
            }
            catch (Exception)
            {

                throw;
            }
        } 

        /// <summary>
        /// 批量删除采购管理
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        public async Task<Response<bool>> DeleteProcureMentList(List<ProcureSelect> dto)
        {
            try
            {
                var list = _procureManagementRepository.GetListQuery().Where(t => dto.Select(x => x.procurementCode).Contains(t.ProcurementCode)).ToList();
                var plist = _shoppingRepository.GetListQuery().Where(t => list.Select(x => x.ProcurementCode).Contains(t.ProcuremenCode)).ToList();

                if (list != null)
                {
                    using (var tran = _smartWMSContext.Database.BeginTransaction())
                    {
                        try
                        {
                            var result = await _procureManagementRepository.DeleteAsync(list);
                            if (result > 0)
                            {
                                var i = await _shoppingRepository.DeleteAsync(plist);
                                if (i > 0)
                                {
                                    tran.Commit();
                                    return Response<bool>.Ok(true);
                                }
                                else
                                {
                                    //回滚
                                    tran.Rollback();
                                    return Response<bool>.Fail(false);
                                }
                            }
                            else
                            {
                                //回滚
                                tran.Rollback();
                                return Response<bool>.Fail(false);
                            }
                        }
                        catch (Exception)
                        {
                            //回滚
                            tran.Rollback();
                            throw;
                        }
                    }
                }
                else
                {
                    return Response<bool>.Fail(false);
                }
            }
            catch (Exception)
            {
                throw;
            }
        }

        /// <summary>
        /// 编辑采购管理
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        public async Task<Response<bool>> UpdateProcureMent(ProcureMentDtos dto)
        {
            var shopList = dto.ShoppingList;
            var list = shopList.Select(x => new Shopping
            {
                ProductId = x.Id,
                ProcuremenCode = dto.ProcurementCode,
                BuyNumber = x.BuyNumber,
                SumPrice = x.SumPrice,
            }).ToList();
            using (var tran = _smartWMSContext.Database.BeginTransaction())
            {
                try
                {
                    var result = await _procureManagementRepository.UpdateAsync(dto.MapTo<ProcureManagement>());
                    if (result > 0)
                    {
                        var shoppingResult = await _shoppingRepository.DeleteAsync(_shoppingRepository.GetListQuery().Where(t => t.ProcuremenCode == dto.ProcurementCode).ToList());
                        if (shoppingResult > 0)
                        {
                            var shoppingResult1 = await _shoppingRepository.InsertAsync(list);
                            if (shoppingResult1 > 0)
                            {
                                tran.Commit();
                                return Response<bool>.Ok(true);
                            }
                            else
                            {
                                tran.Rollback();
                                return Response<bool>.Fail(false);
                            }
                        }
                        else
                        {
                            tran.Rollback();
                            return Response<bool>.Fail(false);
                        }
                    }
                    else
                    {
                        tran.Rollback();
                        return Response<bool>.Fail(false);
                    }
                }
                catch (Exception)
                {

                    throw;
                }
            }

        }

        /// <summary>
        /// 采购入账
        /// </summary>
        /// <param name="code"></param>
        /// <param name="dto"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        public async Task<Response<bool>> ProcureInAccount( InAccountDto? dto)
        {
            var procureManagement = _procureManagementRepository.GetListQuery();
            var shopping = _shoppingRepository.GetListQuery();
            var payment = _paymentRepository.GetListQuery();
            var product = _productRepository.GetListQuery();
            var list = (from a in procureManagement
                       join b in shopping on a.ProcurementCode equals b.ProcuremenCode
                       join c in product on b.ProductId equals c.Id
                       where a.ProcurementCode == dto.procurementCode
                        select new
                       {
                           c.ProductName,
                           b.SumPrice,
                           a.ProcurementCode,
                           a.DocumentType,
                           a.SaleCode,
                           a.SupplierCode,
                           a.ClientName,
                           a.ContactName,
                           a.Phone,
                           a.ReceiptTime,
                           a.MakerName,
                           a.MakerTime,
                           a.Remark,
                           b.BuyNumber,
                           c.ProductCode,
                           c.DefaultSupplierId,
                           c.Specs,
                           c.Unit,
                           c.Price,
                       }).ToList().FirstOrDefault();
            //给dto赋值
            dto.Name = list.ProductName;
            dto.TypeId = 1;
            dto.Payee = list.ClientName;
            dto.Payable = list.SumPrice;
            dto.NetReceipts = list.SumPrice;
            dto.Residue = 0;
            dto.PayInstitution = "拳头科技";
            dto.LastPaymentDate = list.ReceiptTime;
            dto.State = 0;
            dto.Reviewer= list.MakerName;
            dto.Opinion = list.ObjToBool() ? "已审核" : "未审核";
            dto.Audittime = DateTime.Now;
            dto.Remarks = list.Remark;
            dto.CreateTime = DateTime.Now;

            //添加应付表
            var result = await _paymentRepository.InsertAsync(dto.MapTo<Payment>());
            if (result > 0)
            {
                //修改采购管理表状态
                var procure = await _procureManagementRepository.GetListQuery().FirstOrDefaultAsync(t => t.ProcurementCode == dto.procurementCode);
                procure.ProcurementProcurement= true;
                var result1 = await _procureManagementRepository.UpdateAsync(procure);
                if (result1 > 0)
                {
                    return Response<bool>.Ok(true);
                }
                else
                {
                    return Response<bool>.Fail(false);
                }
            }
            else
            {
                return Response<bool>.Fail(false);
            }
        }

        /// <summary>
        ///  采购退货
        /// </summary>
        /// <param name="procuremenReturns"></param>
        /// <returns></returns>
        public async Task<Response<bool>> ProcureReturn(ProcureReturnDto info)
        {
            var shopList = _shoppingRepository.GetListQuery().Where(x => x.ProcuremenCode == info.ProcurementCode).ToList();
            var list = shopList.Select(x => new ProcuremenReturn
            {
                ProcuremenId = info.ProcuremenId,
                ProductId = x.Id,
                DocumentType = info.DocumentType,
                DocumentState = info.DocumentState,
                UsreName = info.UsreName,
                UserTime = info.UserTime,
                ShipmentsTime = info.ShipmentsTime,
                ReturnNumber = x.BuyNumber,
                ReturnSum = x.SumPrice,
                ProcurementCode = info.ProcurementCode,
                ReturnState = info.ReturnState,
                ReturnTime = info.ReturnTime, 
                AuditRemark = info.AuditRemark,
            }).ToList();
            using (var tran = _smartWMSContext.Database.BeginTransaction())
            {
                try
                {
                    
                    var result = await _procuremenReturnRepository.InsertAsync(list);
                    if (result > 0)
                    {
                        var procure = _procureManagementRepository.GetListQuery().Where(x => x.ProcurementCode == info.ProcurementCode).FirstOrDefault();
                        if(procure != null)
                        {
                            procure.IsReFund = true;
                            procure.ProcurementState = ProcurementState.订单取消;
                            var result1 = await _procureManagementRepository.UpdateAsync(procure);
                            if (result1 > 0)
                            {
                                tran.Commit();
                                return Response<bool>.Ok(true);
                            }
                            else
                            {
                                tran.Rollback();
                                return Response<bool>.Fail(false);
                            }
                        }
                        else
                        {
                            tran.Rollback();
                            return Response<bool>.Fail(false);
                        }
                    }
                    else
                    {
                        tran.Rollback();
                        return Response<bool>.Fail(false);
                    }
                }
                catch (Exception)
                {

                    throw;
                }
            }
            
        }
    }
}
